package com.kexilo.messaging.publisher;

import com.kexilo.messaging.domain.Message;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CompletableFuture;

/**
 * 消息发布者接口
 * 定义了消息发布的抽象接口，不依赖任何具体实现
 * 
 * @author Kexilo
 */
public interface MessagePublisher {
    
    /**
     * 发布消息
     * 
     * @param topic 主题
     * @param payload 消息内容
     * @return 发布结果
     */
    PublishResult publish(String topic, String payload);
    
    /**
     * 发布消息
     * 
     * @param message 消息对象
     * @return 发布结果
     */
    PublishResult publish(Message message);
    
    /**
     * 异步发布消息
     * 
     * @param topic 主题
     * @param payload 消息内容
     * @return 异步发布结果
     */
    CompletableFuture<PublishResult> publishAsync(String topic, String payload);
    
    /**
     * 异步发布消息
     * 
     * @param message 消息对象
     * @return 异步发布结果
     */
    CompletableFuture<PublishResult> publishAsync(Message message);
    
    /**
     * 批量发布消息
     * 
     * @param messages 消息列表
     * @return 批量发布结果
     */
    BatchPublishResult batchPublish(List<Message> messages);
    
    /**
     * 发布带标签的消息
     * 
     * @param topic 主题
     * @param tag 标签
     * @param payload 消息内容
     * @return 发布结果
     */
    PublishResult publishWithTag(String topic, String tag, String payload);
    
    /**
     * 发布带优先级的消息
     * 
     * @param topic 主题
     * @param payload 消息内容
     * @param priority 优先级
     * @return 发布结果
     */
    PublishResult publishWithPriority(String topic, String payload, int priority);
    
    /**
     * 发布延迟消息
     * 
     * @param topic 主题
     * @param payload 消息内容
     * @param delayMillis 延迟时间（毫秒）
     * @return 发布结果
     */
    PublishResult publishDelayMessage(String topic, String payload, long delayMillis);
    
    /**
     * 发布定时消息
     * 
     * @param topic 主题
     * @param payload 消息内容
     * @param timestamp 定时时间戳
     * @return 发布结果
     */
    PublishResult publishScheduledMessage(String topic, String payload, long timestamp);
    
    /**
     * 发布事务消息
     * 
     * @param topic 主题
     * @param payload 消息内容
     * @param transactionId 事务ID
     * @return 发布结果
     */
    PublishResult publishTransactionalMessage(String topic, String payload, String transactionId);
    
    /**
     * 提交事务消息
     * 
     * @param transactionId 事务ID
     * @return 提交结果
     */
    boolean commitTransaction(String transactionId);
    
    /**
     * 回滚事务消息
     * 
     * @param transactionId 事务ID
     * @return 回滚结果
     */
    boolean rollbackTransaction(String transactionId);
    
    /**
     * 发布广播消息
     * 
     * @param topic 主题
     * @param payload 消息内容
     * @return 发布结果
     */
    PublishResult publishBroadcast(String topic, String payload);
    
    /**
     * 发布点对点消息
     * 
     * @param queue 队列名
     * @param payload 消息内容
     * @return 发布结果
     */
    PublishResult publishPointToPoint(String queue, String payload);
    
    /**
     * 发布RPC请求消息
     * 
     * @param topic 主题
     * @param payload 请求内容
     * @param timeout 超时时间（毫秒）
     * @return RPC响应结果
     */
    CompletableFuture<String> publishRpcRequest(String topic, String payload, long timeout);
    
    /**
     * 发布通知消息
     * 
     * @param notificationType 通知类型
     * @param recipients 接收者列表
     * @param title 通知标题
     * @param content 通知内容
     * @return 发布结果
     */
    PublishResult publishNotification(String notificationType, List<String> recipients, 
                                     String title, String content);
    
    /**
     * 发布邮件消息
     * 
     * @param to 收件人
     * @param subject 邮件主题
     * @param content 邮件内容
     * @param attachments 附件列表
     * @return 发布结果
     */
    PublishResult publishEmail(String to, String subject, String content, List<String> attachments);
    
    /**
     * 发布短信消息
     * 
     * @param phoneNumber 手机号
     * @param content 短信内容
     * @param template 短信模板
     * @return 发布结果
     */
    PublishResult publishSms(String phoneNumber, String content, String template);
    
    /**
     * 发布推送消息
     * 
     * @param deviceId 设备ID
     * @param title 推送标题
     * @param content 推送内容
     * @param extra 额外参数
     * @return 发布结果
     */
    PublishResult publishPush(String deviceId, String title, String content, Map<String, Object> extra);
    
    /**
     * 获取发布统计
     * 
     * @return 统计信息
     */
    Map<String, Object> getPublishStatistics();
    
    /**
     * 获取主题发布统计
     * 
     * @param topic 主题
     * @return 主题统计信息
     */
    Map<String, Object> getTopicPublishStatistics(String topic);
    
    /**
     * 检查发布者是否可用
     * 
     * @return 是否可用
     */
    boolean isAvailable();
    
    /**
     * 获取发布者健康状态
     * 
     * @return 健康状态
     */
    Map<String, Object> getHealthStatus();
    
    /**
     * 发布结果
     */
    class PublishResult {
        private final boolean success;
        private final String messageId;
        private final String message;
        private final Throwable exception;
        private final long timestamp;
        
        public PublishResult(boolean success, String messageId, String message) {
            this.success = success;
            this.messageId = messageId;
            this.message = message;
            this.exception = null;
            this.timestamp = System.currentTimeMillis();
        }
        
        public PublishResult(boolean success, String messageId, String message, Throwable exception) {
            this.success = success;
            this.messageId = messageId;
            this.message = message;
            this.exception = exception;
            this.timestamp = System.currentTimeMillis();
        }
        
        public static PublishResult success(String messageId) {
            return new PublishResult(true, messageId, "发布成功");
        }
        
        public static PublishResult success(String messageId, String message) {
            return new PublishResult(true, messageId, message);
        }
        
        public static PublishResult failure(String message) {
            return new PublishResult(false, null, message);
        }
        
        public static PublishResult failure(String message, Throwable exception) {
            return new PublishResult(false, null, message, exception);
        }
        
        // Getters
        public boolean isSuccess() { return success; }
        public String getMessageId() { return messageId; }
        public String getMessage() { return message; }
        public Throwable getException() { return exception; }
        public long getTimestamp() { return timestamp; }
        
        @Override
        public String toString() {
            return String.format("PublishResult{success=%s, messageId='%s', message='%s'}", 
                               success, messageId, message);
        }
    }
    
    /**
     * 批量发布结果
     */
    class BatchPublishResult {
        private final int totalCount;
        private final int successCount;
        private final int failureCount;
        private final List<PublishResult> results;
        private final String message;
        
        public BatchPublishResult(int totalCount, int successCount, int failureCount, 
                                 List<PublishResult> results, String message) {
            this.totalCount = totalCount;
            this.successCount = successCount;
            this.failureCount = failureCount;
            this.results = results;
            this.message = message;
        }
        
        // Getters
        public int getTotalCount() { return totalCount; }
        public int getSuccessCount() { return successCount; }
        public int getFailureCount() { return failureCount; }
        public List<PublishResult> getResults() { return results; }
        public String getMessage() { return message; }
        public boolean isFullSuccess() { return failureCount == 0; }
        public boolean isPartialSuccess() { return successCount > 0 && failureCount > 0; }
        public boolean isFullFailure() { return successCount == 0; }
        public double getSuccessRate() { return totalCount == 0 ? 0.0 : (double) successCount / totalCount; }
        
        @Override
        public String toString() {
            return String.format("BatchPublishResult{total=%d, success=%d, failure=%d, successRate=%.2f%%}", 
                               totalCount, successCount, failureCount, getSuccessRate() * 100);
        }
    }
    
    /**
     * 发布回调接口
     */
    interface PublishCallback {
        /**
         * 发布成功回调
         * 
         * @param result 发布结果
         */
        void onSuccess(PublishResult result);
        
        /**
         * 发布失败回调
         * 
         * @param result 发布结果
         */
        void onFailure(PublishResult result);
        
        /**
         * 发布完成回调
         * 
         * @param result 发布结果
         */
        default void onComplete(PublishResult result) {
            if (result.isSuccess()) {
                onSuccess(result);
            } else {
                onFailure(result);
            }
        }
    }
    
    /**
     * 带回调的异步发布
     * 
     * @param message 消息对象
     * @param callback 发布回调
     */
    default void publishWithCallback(Message message, PublishCallback callback) {
        publishAsync(message).whenComplete((result, exception) -> {
            if (exception != null) {
                callback.onFailure(PublishResult.failure("发布异常", exception));
            } else {
                callback.onComplete(result);
            }
        });
    }
    
    /**
     * 注册发布监听器
     * 
     * @param listener 监听器
     */
    default void registerPublishListener(PublishListener listener) {
        // 默认空实现
    }
    
    /**
     * 移除发布监听器
     * 
     * @param listener 监听器
     */
    default void removePublishListener(PublishListener listener) {
        // 默认空实现
    }
    
    /**
     * 发布监听器接口
     */
    interface PublishListener {
        /**
         * 发布前事件
         * 
         * @param message 消息对象
         */
        default void beforePublish(Message message) {}
        
        /**
         * 发布成功事件
         * 
         * @param message 消息对象
         * @param result 发布结果
         */
        default void onPublishSuccess(Message message, PublishResult result) {}
        
        /**
         * 发布失败事件
         * 
         * @param message 消息对象
         * @param result 发布结果
         */
        default void onPublishFailure(Message message, PublishResult result) {}
        
        /**
         * 发布完成事件
         * 
         * @param message 消息对象
         * @param result 发布结果
         */
        default void afterPublish(Message message, PublishResult result) {}
    }
}
